package com.gps.funnymath.abstractItems;

import com.gps.funnymath.concreteItems.ConcreteNumber;
import com.gps.funnymath.concreteItems.ConcreteToken;

public class AbstractOperation implements AbstractToken{
	
	AbstractNumber abstractNumber1;
	AbstractNumber abstractNumber2;
	char operation;
	AbstractOperation abstractOperation1;
	AbstractOperation abstractOperation2;
	
	ConcreteToken lastConcreteToken;
	
	public AbstractOperation(AbstractNumber abstractNumber1, 
			char operation, AbstractNumber abstractNumber2){
		
		this.operation = operation;

		this.abstractNumber1 = abstractNumber1;
		this.abstractNumber2 = abstractNumber2;
		
		this.abstractOperation1 = null;
		this.abstractOperation2 = null;

		lastConcreteToken = null;
	}
	
	public AbstractOperation(AbstractOperation abstractOperation1,
			char operation, AbstractOperation abstractOperation2){
		
		this.operation = operation;
		
		this.abstractNumber1 = null;
		this.abstractNumber2 = null;
		
		this.abstractOperation1 = abstractOperation1;
		this.abstractOperation2 = abstractOperation2;
		
		lastConcreteToken = null;
	}
	
	public AbstractOperation(AbstractOperation abstractOperation1,
			char operation, AbstractNumber abstractNumber2){
		
		this.operation = operation;
		
		this.abstractNumber1 = null;
		this.abstractNumber2 = abstractNumber2;
		
		this.abstractOperation1 = abstractOperation1;
		this.abstractOperation2 = null;
		
		lastConcreteToken = null;
	}
	
	public AbstractOperation(AbstractNumber abstractNumber1,
			char operation, AbstractOperation abstractOperation2){
		
		this.operation = operation;
		
		this.abstractNumber1 = abstractNumber1;
		this.abstractNumber2 = null;
		
		this.abstractOperation1 = null;
		this.abstractOperation2 = abstractOperation2;
		
		lastConcreteToken = null;
	}

	@Override
	public ConcreteToken instantiate() {
		
		int result = -1;
		int n1, n2;
		
		if(abstractNumber1 != null)
			n1 = abstractNumber1.getConcreteNumber().getInteger();
		else
			n1 = abstractOperation1.getResult().getInteger();
			
		if(abstractNumber2 != null)
			n2 = abstractNumber2.getConcreteNumber().getInteger();
		else
			n2 = abstractOperation2.getResult().getInteger();

		switch(operation){
		
		case '+':
			result = n1 + n2;
			break;
			
		case '-':
			result = n1 - n2;
			break;
			
		case '*':
			result = n1 * n2;
			break;
			
		case '/':
			result = n1 / n2;
			break;
			
		}
		
		lastConcreteToken = new ConcreteNumber(result);
		
		return lastConcreteToken;
	}

	@Override
	public ConcreteToken getLastInstantiation() {
		return lastConcreteToken;
	}
	
	@Override
	public ConcreteToken getConcreteToken() {
		if(lastConcreteToken != null)
			return lastConcreteToken;

		return instantiate();
	}
	
	public ConcreteNumber getResult(){
		return (ConcreteNumber)getConcreteToken();
	}
	
	@Override
	public void clearInstantiationReferences() {
		lastConcreteToken = null;
	}

}
